package dockerdemo

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

type response struct {
	Count   int                    `json:"count"`
	Next    string                 `json:"next"`
	Results responseResultSortable `json:"results"`
}

type responseResult struct {
	Name          string    `json:"name"`
	FullSize      int       `json:"full_size"`
	V2            bool      `json:"v2"`
	TagStatus     string    `json:"tag_status"`
	TagLastPulled time.Time `json:"tag_last_pulled"`
	TagLastPushed time.Time `json:"tag_last_pushed"`
}

type responseResultSortable []responseResult

func (r responseResultSortable) Len() int {
	return len(r)
}

func (r responseResultSortable) Less(i, j int) bool {
	return r[i].Name > r[j].Name
}

func (r responseResultSortable) Swap(i, j int) {
	r[i], r[j] = r[j], r[i]
}

func request(name, tag, num string) {
	url := fmt.Sprintf("https://registry.hub.docker.com/v2/repositories/library/%s/tags/?name=%s&page_size=%s", name, tag, num)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Printf("Get information from registry.hub.docker.com err: %v\n", err)
		return
	}
	defer resp.Body.Close()

	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Read data err: %v\n", err)
		return
	}

	// fmt.Println(url)
	// fmt.Printf("data json:\n%s\n", respBody)
	parse(name, respBody)
}

func parse(name string, respBody []byte) {
	respData := new(response)
	err := json.Unmarshal(respBody, &respData)
	if err != nil {
		fmt.Printf("json.Unmarshal data err: %v\n", err)
		return
	}
	if len(respData.Results) == 0 {
		fmt.Printf("there is no tag data for name: %s\n", name)
		return
	}

	// resort results
	sort.Sort(respData.Results)

	// beauty format
	var maxLengthForName int
	for _, v := range respData.Results {
		if len(v.Name) > maxLengthForName {
			maxLengthForName = len(v.Name)
		}
	}

	//fmt.Printf("Tags for %s:\n\n", name)
	fmt.Printf("%s%s%10s   %s\n", "TAG", strings.Repeat(" ", maxLengthForName), "SIZE(MB)", "LASTPUSH")
	for _, v := range respData.Results {
		fmt.Printf("%s%s   %10d   %s\n",
			v.Name, strings.Repeat(" ", maxLengthForName-len(v.Name)),
			v.FullSize/1024/1024,
			v.TagLastPushed.Format(time.RFC3339),
		)
	}
}

func SearchTag(name , tag, num string) {
	request(name, tag, num)
}